package com.xg.util.export;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.xg.model.entity.Styleable;
import org.apache.poi.ss.usermodel.*;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

public class ExcelStyleHandler implements SheetWriteHandler, CellWriteHandler {

    // 缓存需要特殊样式的行（行号→数据对象）
    private final Map<Integer, Styleable> specialRows = new HashMap<>();

    // 维护字段名与列索引的映射关系
    private final Map<String, Integer> fieldIndexMap;

    private final int rowOffset; // 行号偏移量

    // 构造函数：支持多实体类，收集所有需要特殊样式的行
    public ExcelStyleHandler(List<?> dataList, Class<?> entityClass, int rowOffset) {
        this.rowOffset = rowOffset;

        for (Object obj : dataList) {
            if (obj instanceof Styleable) {
                Styleable item = (Styleable) obj;
                if (!StringUtils.isEmpty(item.getOperationType()) && item.getNum() != null) {
                    // 存储时加上偏移量，确保与Excel行号一致
                    specialRows.put(item.getNum() + rowOffset, item);
                }
            }
        }

        this.fieldIndexMap = initializeFieldIndexMap(entityClass);
    }

    // 初始化字段名与列索引的映射
    private Map<String, Integer> initializeFieldIndexMap(Class<?> entityClass) {
        Map<String, Integer> map = new HashMap<>();
        Field[] fields = entityClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation != null) {
                // 使用注解中的值作为字段名
                map.put(field.getName(), i);
            }
        }
        return map;
    }

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        // 冻结窗格逻辑（根据实际需求调整）
        Sheet sheet = writeSheetHolder.getSheet();
        if ("第一页".equals(sheet.getSheetName())) {
            sheet.createFreezePane(0, 3); // 三级表头
        } else if ("第二页".equals(sheet.getSheetName())) {
            sheet.createFreezePane(0, 3); // 三级表头
        }
    }

    @Override
    public void afterCellDispose(
            WriteSheetHolder writeSheetHolder,
            WriteTableHolder writeTableHolder,
            List<WriteCellData<?>> cellDataList,
            Cell cell,
            Head head,
            Integer relativeRowIndex,
            Boolean isHead
    ) {
        int rowIndex = cell.getRowIndex();
        int columnIndex = cell.getColumnIndex();

        // 处理表头样式
        if (isHead) {
            applyHeaderStyle(cellDataList);
            return;
        }

        // 设置默认样式
        setDefaultStyle(cellDataList);

        // 获取当前行的特殊样式数据
        Styleable item = specialRows.get(rowIndex);
        if (item != null) {
            try {
                // 使用列索引替代字段名
                applyStyles(
                        item,
                        columnIndex,
                        cellDataList
                );
            } catch (Exception e) {
                System.err.println("处理" + item.getClass().getSimpleName() + "样式异常：" + e.getMessage());
            }
        }
    }

    /**
     * 应用样式（适配多实体类）
     * @param item 数据对象（OneData/TwoData等）
     * @param columnIndex 当前单元格的列索引
     * @param cellDataList 单元格数据列表
     */
    private void applyStyles(
            Styleable item,
            int columnIndex,
            List<WriteCellData<?>> cellDataList
    ) {
        String operationType = item.getOperationType();
        String modifiedField = item.getModifiedField();

        if (operationType == null || operationType.isEmpty()) {
            return;
        }

        // 创建基础样式
        WriteCellStyle style = createBaseCellStyle();

        // 处理修改操作（仅标记被修改的字段）
        if ("update".equals(operationType) && modifiedField != null && !modifiedField.isEmpty()) {
            for (String field : modifiedField.split(",")) {
                // 通过字段名获取列索引
                Integer targetCol = fieldIndexMap.get(field.trim());
                if (targetCol != null && targetCol == columnIndex) {
                    StyleStrategyFactory.getStrategy(operationType, columnIndex, targetCol).applyStyle(style);
                    break;
                }
            }
        } else {
            // 处理新增/删除等操作（整行标记）
            StyleStrategyFactory.getStrategy(operationType, -1, -1).applyStyle(style);
        }

        // 应用样式到单元格
        cellDataList.forEach(cellData -> cellData.setWriteCellStyle(style));
    }

    // 以下为辅助方法（样式创建）
    private void applyHeaderStyle(List<WriteCellData<?>> cellDataList) {
        WriteCellStyle headerStyle = createHeaderCellStyle();

        // 为每个单元格应用表头样式（包含边框）
        for (WriteCellData<?> cellData : cellDataList) {
            cellData.setWriteCellStyle(headerStyle);
        }
    }

    private void setDefaultStyle(List<WriteCellData<?>> cellDataList) {
        WriteCellStyle defaultStyle = createBaseCellStyle();
        defaultStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        cellDataList.forEach(cellData -> cellData.setWriteCellStyle(defaultStyle));
    }

    private WriteCellStyle createBaseCellStyle() {
        WriteCellStyle style = new WriteCellStyle();
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        return style;
    }

    private WriteCellStyle createHeaderCellStyle() {
        WriteCellStyle style = new WriteCellStyle();
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        style.setHorizontalAlignment(HorizontalAlignment.CENTER);

        WriteFont font = new WriteFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 12);
        style.setWriteFont(font);
        return style;
    }
}